package org.ykhl.mq.dispatcher;

import org.ykhl.log.commons.sender.LogSender;
import org.ykhl.mq.commons.Constants;
import org.ykhl.mq.dispatcher.rule.MqMessageTransformer;
import org.ykhl.mq.commons.BaseMessage;

import org.ykhl.model.RetInfo;

import java.util.Map;

public abstract class MqMessageDispatcher<T extends BaseMessage> {
	private volatile boolean running = false;
	protected String mqNameServerAddress;
	protected String mqConsumerGroupName = Constants.MQ_DISPATCHER_CONSUMER;
	protected String mqProducerGroupName = Constants.MQ_DISPATCHER_PRODUCER;
	protected MqMessageTransformer<T> mqMessageTransformer;
	protected LogSender logSender;

	protected String hospitalName;
	protected Boolean useSsl;
	protected int  timeOut = 60000 ;//默认超时时间为60s
	public final void setUseSsl(boolean useSsl) {
		this.useSsl = useSsl;
	}

	public final void setHospitalName(String hospitalName) {
		this.hospitalName = hospitalName;
	}

	public final void setTimeOut(int timeOut){ this.timeOut = timeOut;}

	public final void setMqNameServerAddress(String mqNameServerAddress) {
		this.mqNameServerAddress = mqNameServerAddress;
	}
	public final void setMqConsumerGroupName(String mqConsumerGroupName) {
		this.mqConsumerGroupName = mqConsumerGroupName;
	}
	public final void setMqProducerGroupName(String mqProducerGroupName) {
		this.mqProducerGroupName = mqProducerGroupName;
	}

	public final void setMqMessageTransformer(MqMessageTransformer<T> mqMessageTransformer) {
		this.mqMessageTransformer = mqMessageTransformer;
	}
	public final void setLogSender(LogSender logSender) {
		this.logSender = logSender;
	}

	public final void fatal(String msg, Exception e){
		logSender.error(msg, e);
		//TODO: temporarily avoid destroy in request-response scenario.
		destroyFromInside();
	}

	public final void init() throws Exception{
		if(running)
			return;
		doInit();
		hospitalInit();//用于自定义医院端适配的时候初始话一些参数
		running = true;
	}

	public final void destroy(){
		synchronized (this) {
			if (!running)
				return;
			running = false;
		}
		doDestroy();
	}

	public final void destroyFromInside(){
		synchronized (this) {
			if (!running)
				return;
			running = false;
		}

		new Thread(new Runnable() {
			@Override
			public void run() { doDestroy(); }
		}).start();
	}

	protected abstract void doInit() throws Exception;
	protected abstract void doDestroy();
	public abstract boolean sendToAppserver(T message);

	/**
	 * 获取院内消息
	 * @param params
	 * @return
	 */
	public abstract String getHosMessageInfo(Map<String, Object> params)throws Exception;

	protected abstract void hospitalInit();

	public abstract RetInfo trans(Map<String, Object > params);
}
